package com.wish233.server.impl;

import com.wish233.application.RpcApplication;
import com.wish233.model.rpc.RpcRequest;
import com.wish233.model.rpc.RpcResponse;
import com.wish233.register.local.LocalServiceRegister;
import com.wish233.serializer.Serializer;
import com.wish233.serializer.factory.SerializerFactory;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author WHH
 */
@Slf4j
public class HttpServerHandler implements Handler<HttpServerRequest> {
    private final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());

    @Override
    public void handle(HttpServerRequest httpServerRequest) {
        //将请求反序列化为对象
        httpServerRequest.bodyHandler(
                buffer -> {
                    byte[] bytes = buffer.getBytes();
                    RpcRequest rpcRequest = null;
                    try {
                        rpcRequest = serializer.deserialize(bytes, RpcRequest.class);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    RpcResponse rpcResponse = new RpcResponse();
                    if (rpcRequest == null) {
                        rpcResponse.setMessage("请求是null");
                        doResponse(httpServerRequest, rpcResponse, serializer);
                        return;
                    }
                    String serviceName = rpcRequest.getServiceName();
                    String methodName = rpcRequest.getMethodName();
                    Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
                    Object[] args = rpcRequest.getArgs();
                    //从本地注册器获取实现类
                    //根据请求寻找相应的实现类调用方法（反射）
                    try {
                        Class<?> service = LocalServiceRegister.getService(serviceName);
                        Method method = service.getMethod(methodName, parameterTypes);
                        Object result = method.invoke(service.newInstance(), args);
                        //调用后的方法序列化返回
                        rpcResponse.setData(result);
                        rpcResponse.setDataType(method.getReturnType());
                        rpcResponse.setMessage("OK");
                    } catch (Exception e) {
                        rpcResponse.setException(e);
                        rpcResponse.setMessage(e.getMessage());
                        e.printStackTrace();
                    }
                    doResponse(httpServerRequest, rpcResponse, serializer);
                }
        );

    }

    void doResponse(HttpServerRequest httpServerRequest, RpcResponse rpcResponse, Serializer serializer) {
        HttpServerResponse httpServerResponse = httpServerRequest.response()
                .putHeader("content-type", "application/json");
        try {
            byte[] serialize = serializer.serialize(rpcResponse);
            httpServerResponse.end(Buffer.buffer(serialize));
        } catch (IOException e) {
            e.printStackTrace();
            httpServerResponse.end(Buffer.buffer());
        }
    }
}
